

package com.plian.system.exception;

import cn.hutool.core.map.MapUtil;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.UserData;
import com.plian.system.config.exception.*;
import com.plian.system.entity.sys.Loginfo;
import com.plian.system.enumeratea.LogStatusEnum;
import com.plian.system.mapper.sys.LoginfoMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;


/**
 * 异常处理器
 *

 * @since 1.0.0
 */
@Slf4j
@RestControllerAdvice
@AllArgsConstructor
public class GzwExceptionHandler {
    private final LoginfoMapper loginfoMapper;


    @ExceptionHandler(SecureException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public R handleSecureException(SecureException ex, HttpServletRequest request){
        log.error(ex.getMessage(), ex);
        if (null == request.getAttribute("LOG_RECORDED")) {
            // 仅记录未处理过的异常
            saveLog(ex);
        }
        return R.fail(CommonCode.UNAUTHORISE, ex.getMessage());
    }

    @ExceptionHandler(ServiceException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R handleServiceException(ServiceException ex, HttpServletRequest request){
        log.error(ex.getMessage(), ex);
        if (null == request.getAttribute("LOG_RECORDED")) {
            // 仅记录未处理过的异常
            saveLog(ex);
        }
        return R.fail(CommonCode.ERROR, ex.getMessage());
    }

    @ExceptionHandler(RefreshTokenException.class)
    @ResponseStatus(HttpStatus.OK)
    public R handleRefreshTokenException(RefreshTokenException ex, HttpServletRequest request){
        log.error(ex.getMessage(), ex);
        if (null == request.getAttribute("LOG_RECORDED")) {
            // 仅记录未处理过的异常
            saveLog(ex);
        }
        return R.fail(CommonCode.REFRESH_TOKEN_ERROR, ex.getMessage());
    }
    @ExceptionHandler(TokenException.class)
    @ResponseStatus(HttpStatus.OK)
    public R handleTokenException(TokenException ex, HttpServletRequest request) {
        log.error(ex.getMessage(), ex);
        if (null == request.getAttribute("LOG_RECORDED")) {
            // 仅记录未处理过的异常
            saveLog(ex);
        }
        return R.fail(CommonCode.UNTOKEN, ex.getMessage());
    }
    @ExceptionHandler(MyRuntimeException.class)
    @ResponseStatus(HttpStatus.OK)
    public R handleMyRuntimeException(MyRuntimeException ex, HttpServletRequest request){
        log.error(ex.getMessage(), ex);
        if (null == request.getAttribute("LOG_RECORDED")) {
            // 仅记录未处理过的异常
            saveLog(ex);
        }
        return R.fail(CommonCode.ERROR, ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public R handleException(Exception ex, HttpServletRequest request){
//        ObjResult objResult = new ObjResult(CommonCode.FAIL);
//        objResult.setMessage(ex.getMessage());
        log.error(ex.getMessage(), ex);
        if (null == request.getAttribute("LOG_RECORDED")) {
            // 仅记录未处理过的异常
            saveLog(ex);
        }
        return R.fail(CommonCode.ERROR, ex.getMessage());
    }

    /**
     * 保存异常日志
     */
    @Async("ttlExecutor")
    protected void saveLog(Exception ex) {
        Loginfo log = new Loginfo();
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if(null != requestAttributes){
            String annotationValue = (String) requestAttributes.getAttribute("LOG_OPERATION_VALUE", RequestAttributes.SCOPE_REQUEST);
            log.setOperation(annotationValue);
        }
        log.setLogType(3);
        //登录用户信息
        UserData user = TokenUtil.getUserData();
        if (user != null) {
            log.setUserId(user.getUserId());
            log.setUserName(user.getUserName());
        }

        //请求相关信息
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        log.setCallingInterface(request.getRequestURI());
        log.setRequestWay(request.getMethod());
        log.setIp(IpUtils.getIpAddr(request));
        log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
        Map<String, String> params = HttpContextUtils.getParameterMap(request);
        if (MapUtil.isNotEmpty(params)) {
            log.setRequestParams(JsonUtils.toJsonString(params));
        }

        log.setStatus(LogStatusEnum.FAIL.value());
        log.setRequestTime(cn.hutool.core.date.DateUtil.date());
        log.setRequestDuration(0L);
        //异常信息
        log.setErrorInfo(ExceptionUtils.getStackTrace(ex));
        log.setId(UuidUtil.get32UUID());
        //保存
        loginfoMapper.save(log);
    }
}